/// Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.Security.Permissions;

namespace Microsoft.VSPowerToys.Common.TaskManager
{
    
    /// <summary>
    /// This exception has to be raised from PerformTask method whenever task could not
    /// be completed successfully.
    /// 
    /// It contains detailed information on why the task failed.
    /// </summary>
	[Serializable]
    public class TaskException : Exception
    {

        private Task ownerTask;

        public Task OwnerTask
        {
            get
            {
                return ownerTask;
            }
        }

		/// <summary>
		/// Default required constructor to implement the ISerializable interface
		/// </summary>
		public TaskException() 
			: base()
		{
		}

		/// <summary>
		/// Required constructor to implement the ISerializable interface
		/// </summary>
		public TaskException(string message)
			: base(message)
		{
		}

		/// <summary>
		/// Required constructor to implement the ISerializable interface
		/// </summary>
		public TaskException(string message, Exception exception)
			: base(message, exception)
		{
		}

		/// <summary>
		/// Constructor to initialize the task data of the exception
		/// </summary>
        public TaskException(Task task) 
        {
            this.ownerTask = task;
        }

		/// <summary>
		/// Constructor to initialize the task data of the exception, along with the message string
		/// </summary>
        public TaskException(string message, Task task) : base(message) 
        {
            this.ownerTask = task;
        }

		/// <summary>
		/// Constructor to initialize the task data of the exception, along with the message string, and an inner exception
		/// </summary>
        public TaskException(string message, Exception inner, Task task) : base(message, inner) 
        {
            this.ownerTask = task;
        }

        protected TaskException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { }

		/// <summary>
		/// Method required to properly implement ISerializable, we don't really have anything to do here.
		/// </summary>
		[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
		public override void GetObjectData( SerializationInfo info, StreamingContext context )
		{
			base.GetObjectData(info, context);
		}
    }

    /// <summary>
    /// An exception for errors during MSI installation process
    /// </summary>
	[Serializable]
    public class MsiException : TaskException
    {

        private string installFile;

        private int errorCode;

		/// <summary>
		/// The install file being executed
		/// </summary>
        public string InstallFile
        {
            get
            {
                return installFile;
            }
        }

        /// <summary>
        /// Error code returned from msiexec process.
        /// </summary>
        public int ErrorCode 
        {
            get
            {
                return this.errorCode;
            }
        }

        /// <summary>
        /// Returns a message according to error code returned from msiexec process.
        /// </summary>
        public override string Message
        {
            get
            {
                switch (this.errorCode)
                {
                    case 0:
                        return "Success";
                    case 1602:
                        return "User cancelled installation";
                    case 1619:
                    case 1620:
                        return "MSI file could not be opened";
                    case 1638:
                        return "Product is already installed";
                    default:
                        return "Unknown error code";
                }
            }
        }

        /// <summary>
        /// Creates a new MSIException.
        /// </summary>
        /// <param name="installName">Name of the MSI file that was being processed</param>
        /// <param name="errorCode">Error code from msiexec process</param>
        /// <param name="task">Task that owns this installation</param>
        public MsiException(string installName, int errorCode, Task task) : base(task)
        {
            this.installFile = installName;
            this.errorCode = errorCode;
        }

		/// <summary>
		/// Default required constructor to implement the ISerializable interface
		/// </summary>
		public MsiException() 
			: base()
		{
		}

		/// <summary>
		/// Required constructor to implement the ISerializable interface
		/// </summary>
		public MsiException(string message)
			: base(message)
		{
		}

		/// <summary>
		/// Required constructor to implement the ISerializable interface
		/// </summary>
		public MsiException(string message, Exception exception)
			: base(message, exception)
		{
		}

        protected MsiException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { }

		/// <summary>
		/// Method required to properly implement ISerializable, we don't really have anything to do here.
		/// </summary>
		[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]
		public override void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			base.GetObjectData(info, context);
		}
    }

    /// <summary>
    /// An exception for errors during EXE installation process
    /// </summary>
    [Serializable]
    public class ExeException : TaskException
    {

        private string installFile;

        private int errorCode;

        /// <summary>
        /// The install file being executed
        /// </summary>
        public string InstallFile
        {
            get
            {
                return installFile;
            }
        }

        /// <summary>
        /// Error code returned from the setup process.
        /// </summary>
        public int ErrorCode
        {
            get
            {
                return this.errorCode;
            }
        }

        /// <summary>
        /// Returns a message according to error code returned from the setup process.
        /// </summary>
        public override string Message
        {
            get
            {
                switch (this.errorCode)
                {
                    case 0:
                        return "Success";
                    default:
                        return "Unknown error code";
                }
            }
        }

        /// <summary>
        /// Creates a new ExeException.
        /// </summary>
        /// <param name="installName">Name of the setup file that was being processed</param>
        /// <param name="errorCode">Error code from the setup process</param>
        /// <param name="task">Task that owns this installation</param>
        public ExeException(string installName, int errorCode, Task task)
            : base(task)
        {
            this.installFile = installName;
            this.errorCode = errorCode;
        }

        /// <summary>
        /// Default required constructor to implement the ISerializable interface
        /// </summary>
        public ExeException()
            : base()
        {
        }

        /// <summary>
        /// Required constructor to implement the ISerializable interface
        /// </summary>
        public ExeException(string message)
            : base(message)
        {
        }

        /// <summary>
        /// Required constructor to implement the ISerializable interface
        /// </summary>
        public ExeException(string message, Exception exception)
            : base(message, exception)
        {
        }

        protected ExeException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { }

        /// <summary>
        /// Method required to properly implement ISerializable, we don't really have anything to do here.
        /// </summary>
        [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }
    }
}
